package xuyuanjun.paymenthandler.context;

import java.util.concurrent.ConcurrentHashMap;

import xuyuanjun.paymenthandler.entities.Account;
import xuyuanjun.paymenthandler.entities.Currency;
import xuyuanjun.paymenthandler.entities.Transaction;

/**
 * 
 * @author Xu Yuanjun
 *
 */
public class AccountsContext {
	
	private ConcurrentHashMap<Currency, Account> accounts;	
	private CurrencySet currencySet;
	
	//singleton
	private volatile static AccountsContext instance;
	
	private AccountsContext() {
		accounts = new ConcurrentHashMap<Currency, Account>();
		currencySet = new CurrencySet();
	}

	public static AccountsContext getInstance() {
		if (instance == null) {
			synchronized (AccountsContext.class) {
				if (instance == null) {
					instance = new AccountsContext();
				}
			}
		}
		return instance;
	}
	
	public void processTransaction(Transaction t) {
		String currencyCode = t.getCurrencyCode();
		Currency currency = currencySet.isCurrencyExists(currencyCode) ? 
							currencySet.getCurrency(currencyCode) :
							currencySet.addCurrency(currencyCode);
		Account account = accounts.containsKey(currency) ? 
						  accounts.get(currency) : 
						  new Account(currency, 0);
		//update balance, synchronized		
		if (account.getBalance() + t.getAmount() < 0) {
			System.out.println("Warning: transaction aborting for the balance is not enough");
			return;
		}
		account.setBalance(account.getBalance() + t.getAmount());		
		accounts.put(currency, account);
	}
	
	public void outputAllAccountsBalance() {
		System.out.println("========================================================");
		for(Account a : accounts.values()) {
			if (a != null) {
				//output the account info
				String info = null;
				if ((info = a.getAccountBalanceInfo()) != null) {
					System.out.println(info);
				}
			}
		}
		System.out.println("========================================================");
	}
	
	public double checkAccountBalance(String currencyCode) {
		if (!currencySet.isCurrencyExists(currencyCode) ||
		    !accounts.containsKey(currencySet.getCurrency(currencyCode))) {
			return 0;
		} else {
			return accounts.get(currencySet.getCurrency(currencyCode)).getBalance();
		}
	}
}
